package com.ruoyi.project.biz.service.impl;

import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.biz.dao.CredentialsDao;
import com.ruoyi.project.biz.dao.FlowCredentialsDao;
import com.ruoyi.project.biz.dao.FlowInstDao;
import com.ruoyi.project.biz.dao.FlowRecordDao;
import com.ruoyi.project.biz.entity.*;
import com.ruoyi.project.biz.service.FlowInstService;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Service
public class FlowInstServiceImpl implements FlowInstService {
    private FlowInstDao flowInstDao;
    private FlowRecordDao flowRecordDao;
    private FlowCredentialsDao flowCredentialsDao;
    private CredentialsDao credentialsDao;
    private ISysUserService sysUserService;

    @Autowired
    public void setFlowInstDao(FlowInstDao flowInstDao) {
        this.flowInstDao = flowInstDao;
    }

    @Autowired
    public void setFlowRecordDao(FlowRecordDao flowRecordDao) {
        this.flowRecordDao = flowRecordDao;
    }

    @Autowired
    public void setFlowCredentialsDao(FlowCredentialsDao flowCredentialsDao) {
        this.flowCredentialsDao = flowCredentialsDao;
    }

    @Autowired
    public void setCredentialsDao(CredentialsDao credentialsDao) {
        this.credentialsDao = credentialsDao;
    }

    @Autowired
    public void setSysUserService(ISysUserService sysUserService) {
        this.sysUserService = sysUserService;
    }

    @Override
    public void test() {}

    @Override
    public Page<FlowInstDO> getList(InstQueryEntity queryEntity, Pageable pageable) {
        Page<FlowInstDO> list = null;
        if (queryEntity.getLoginUser().getUser().isAdmin()) {
             list = flowInstDao.findAll(pageable);
        } else {
            list = flowInstDao.findAllByUserId(queryEntity.getLoginUser().getUser().getUserId(), pageable);
        }
        return list;
    }

    private SysUser getAdmin() {
        return sysUserService.selectUserById(1L);
    }

    @Override
    public AjaxResult addFlow(InstEntity instEntity) {
        FlowInstDO instDO = new FlowInstDO();
        LoginUser user = instEntity.getLoginUser();
        Date addTime = new Date();

        if (user == null) {
            return AjaxResult.error("请先登录！");
        }

        //流程实例表
        instDO.setUserDeptName(user.getUser().getDept().getDeptName());
        instDO.setUserDeptId(user.getUser().getDeptId());
        instDO.setFinishFlag(0);
        instDO.setCreateTime(addTime);
        instDO.setUserId(user.getUser().getUserId());
        instDO.setUserName(user.getUsername());
        flowInstDao.save(instDO);

        //关联证书表
        List<Long> credIds = instEntity.getCredentialsIds();
        for (Long id : credIds) {
            CredentialsDO c = credentialsDao.getOne(id);
            FlowCredentialsDO fc = new FlowCredentialsDO();
            fc.setCredentialsId(id);
            fc.setAddTime(addTime);
            fc.setBorrowFlag(0);
            fc.setCredentialsName(c.getCredentialsName());
            fc.setCredentialsTypeId(c.getCredentialsTypeId());
            fc.setInstId(instDO.getInstId());
            fc.setReturnFlag(-1);
            fc.setReturnTime(null);
            flowCredentialsDao.save(fc);
        }

        //流转记录表
        FlowRecordDO recordDO = new FlowRecordDO(instDO.getInstId(),
                "申请",
                addTime,
                addTime,
                user.getUser().getUserId(),
                user.getUsername(),
                instEntity.getRecordMsg(),
                1
                );
        flowRecordDao.save(recordDO);

        //流转到下一环节
        FlowRecordDO nextRecordDO = getAdminRecordDo(instDO.getInstId(), "审批", addTime, 2);
        flowRecordDao.save(nextRecordDO);

        return AjaxResult.success("流程发起成功！");
    }

    private FlowRecordDO getAdminRecordDo(Long instId, String segmentName, Date addTime, int seq) {
        FlowRecordDO adminRecordDO = new FlowRecordDO(instId,
                segmentName,
                addTime,
                null,
                1L,
                getAdmin().getUserName(),
                "",
                seq
        );
        return adminRecordDO;
    }

    @Override
    public AjaxResult nextStep(RecordEntity recordEntity) {
        FlowRecordDO recordDO = flowRecordDao.findByInstIdAndEndTimeIsNull(recordEntity.getInstId());
        if (recordDO == null) {
            return AjaxResult.error("环节信息异常，流程已归档！");
        }

        Date processTime = new Date();
        FlowRecordDO nextRecordDO = null;
        String segmentName = "";

        if (recordEntity.getStep() == 1) {//下一步
            switch (recordDO.getSegmentName()) { //申请、审批、借出、归档
                case "申请":
                    segmentName = "审批";
                    break;
                case "审批":
                    segmentName = "借出";
                    break;
                case "借出":
                    segmentName = "归档";
                    recordDO.setEndTime(processTime);
                    recordDO.setRecordMsg(recordEntity.getRecordMsg());
                    flowRecordDao.save(recordDO);

                    nextRecordDO = new FlowRecordDO(recordEntity.getInstId(),
                            segmentName,
                            processTime,
                            processTime,
                            1L,
                            getAdmin().getUserName(),
                            "流程结束，已归档",
                            recordDO.getFlowSeq() + 1);
                    flowRecordDao.save(nextRecordDO);

                    FlowInstDO instDO = flowInstDao.getOne(recordEntity.getInstId());
                    instDO.setFinishFlag(1);
                    instDO.setFinishTime(processTime);
                    flowInstDao.save(instDO);
                    return AjaxResult.success("归档成功！");
                default:
                    return AjaxResult.error("未定义的环节:" + recordDO.getSegmentName());
            }
            recordDO.setEndTime(processTime);
            recordDO.setRecordMsg(recordEntity.getRecordMsg());
            flowRecordDao.save(recordDO);

            nextRecordDO = getAdminRecordDo(recordEntity.getInstId(), segmentName, processTime, recordDO.getFlowSeq() + 1);
            flowRecordDao.save(nextRecordDO);
        } else if (recordEntity.getStep() == -1) {//回退
            switch (recordDO.getSegmentName()) { //申请、审批、借出、归档
                case "申请":
                case "借出":
                case "归档":
                    return AjaxResult.error("当前环节不能回退");
                case "审批":
                    recordDO.setEndTime(processTime);
                    recordDO.setRecordMsg(recordEntity.getRecordMsg());
                    flowRecordDao.save(recordDO);

                    segmentName = "申请";
                    FlowRecordDO start = flowRecordDao.findByInstIdAndFlowSeq(recordEntity.getInstId(), 1);
                    nextRecordDO = new FlowRecordDO(start.getInstId(),
                            segmentName,
                            processTime,
                            null,
                            start.getProcessUserId(),
                            start.getProcessUserName(),
                            "",
                            recordDO.getFlowSeq() + 1);
                    flowRecordDao.save(nextRecordDO);
                    break;
                default:
                    return AjaxResult.error("未定义的环节:" + recordDO.getSegmentName());
            }
        } else {
            return AjaxResult.error("step 参数错误！");
        }
        return AjaxResult.success("流转成功！当前环节：" + segmentName);
    }

    @Override
    public int backStep() {
        return 0;
    }

    @Override
    public List<FlowRecordDO> getRecordsInfo(Long instId) {
        return flowRecordDao.findAllByInstIdOrderByFlowSeqDesc(instId);
    }
}
